package com.ruoyi.activiti.service;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.ruoyi.activiti.domain.MyHistoricTask;
import com.ruoyi.activiti.domain.TaskCondition;
import com.ruoyi.activiti.domain.TaskVo;
import com.ruoyi.activiti.domain.constant.TaskAction;
import com.ruoyi.activiti.mapper.TaskMapper;
import com.ruoyi.activiti.service.cmd.MoveSingleCommand;
import com.ruoyi.activiti.util.ActivitiUtil;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.utils.StringUtils;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.*;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
public class MyTaskService {

    @Autowired
    ManagementService managementService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    IdentityService identityService;
    @Autowired
    HistoryService historyService;
    @Autowired
    TaskService taskService;
    @Autowired
    ProcessInstanceService processInstanceService;
    @Autowired
    ActivitiConvertService convertService;
    @Autowired
    TaskMapper taskMapper;
    @Autowired
    ActivitiUtil activitiUtil;

    /**
     * 查询待办任务列表
     * @param taskCondition
     * @return
     */
    public List<TaskVo> taskList(TaskCondition taskCondition) {
        PageHelper.startPage(taskCondition.getPageNum(), taskCondition.getPageSize());
        List<TaskVo> tasks = taskMapper.taskList(taskCondition);
        if(CollectionUtil.isEmpty(tasks)){
            return tasks;
        }
        tasks.forEach(taskVo -> convertService.fillTaskVo(taskVo));
        return tasks;
    }

    /**
     *
     * @param task
     */
    public void doTask(TaskVo task) {
        if(StringUtils.isEmpty(task.getAction())){
            throw new ActivitiException("参数action不能为空");
        }
        Task actTask = taskService.createTaskQuery()
                .taskId(task.getTaskId())
                .singleResult();
        if(actTask==null){
            throw new ActivitiException("任务不存在，或已被处理");
        }
        //有可能会指定处理人
        String username = StringUtils.isNotEmpty(task.getCreateBy())? task.getCreateBy(): SecurityUtils.getUsername();
        identityService.setAuthenticatedUserId(username);//先登录
        taskService.claim(task.getTaskId(), username);//先签收任务，act_hi_taskinst 表的 assignee 字段才不为 null
        taskService.setDueDate(task.getTaskId(), new Date());//更新执行时间，用于审批历史的排序
        String comment = (StringUtils.isNotEmpty(task.getActionName())?task.getActionName():task.getAction()) + ":";
        comment += StringUtils.isNotEmpty(task.getComment())?task.getComment():"";
        taskService.addComment(task.getTaskId(), actTask.getProcessInstanceId()
                , task.getAction()//处理方式，COMPLETE、BACK等
                , comment);//处理意见，默认空字符串
        taskService.setVariables(task.getTaskId(), task.getVariables());//保存变量
        if(TaskAction.COMPLETE.equals(task.getAction())){//完成任务
            complete(task, actTask);
        }else if(TaskAction.BACK.equals(task.getAction())){//回退任务
            back(task, actTask);
        }else if(TaskAction.REJECT.equals(task.getAction())){//驳回任务
            reject(task, actTask);
        }else if(TaskAction.DELEGATE.equals(task.getAction())){//转办任务
            throw new ActivitiException("暂不支持" + task.getAction());
        }else if(TaskAction.JUMP.equals(task.getAction())){
            jump(task, actTask);
        }else if(TaskAction.DELETE.equals(task.getAction())){
            delete(task, actTask);
        }else{
            throw new ActivitiException("未知的操作：" + task.getAction());
        }
    }

    private void delete(TaskVo task, Task actTask) {
        runtimeService.deleteProcessInstance(actTask.getProcessInstanceId(), task.getActionName());
    }

    private void reject(TaskVo task, Task actTask) {
        Process process = repositoryService.getBpmnModel(actTask.getProcessDefinitionId()).getMainProcess();
        List<MyHistoricTask> histTasks = processInstanceService.selectHistoryList(actTask.getProcessInstanceId());//本流程实例的审批历史
        FlowNode firstNode = activitiUtil.getFirstUserTask(process, histTasks);//获取开始节点后，被执行过的第一个用户任务
        if(firstNode==null){
            throw new ActivitiException("驳回失败，未找到第一个用户任务");
        }
        task.setTargetActivityId(firstNode.getId());
        this.jump(task, actTask);
    }

    private void back(TaskVo task, Task actTask) {
        Process process = repositoryService.getBpmnModel(actTask.getProcessDefinitionId()).getMainProcess();
        FlowNode currentNode = (FlowNode) process.getFlowElement(actTask.getTaskDefinitionKey());
        List<MyHistoricTask> histTasks = processInstanceService.selectHistoryList(actTask.getProcessInstanceId());//本流程实例的审批历史
        FlowNode fromNode = activitiUtil.getLastUserTask(process, currentNode, histTasks);//获取本流程中上一个被执行的用户任务
        if(fromNode==null){
            throw new ActivitiException("驳回失败，未找到上一用户任务");
        }
        task.setTargetActivityId(fromNode.getId());
        this.jump(task, actTask);
    }

    private void complete(TaskVo task, Task actTask) {
        taskService.complete(task.getTaskId());
    }

    private void jump(TaskVo task, Task actTask) {
        //managementService.executeCommand(new DeleteTaskCommand(task.getTaskId()));
        managementService.executeCommand(new MoveSingleCommand(task.getTaskId(), task.getTargetActivityId()));
    }

    public TaskVo getTaskVoById(String taskId) {
        TaskCondition taskCondition = new TaskCondition();
        taskCondition.setTaskId(taskId);
        List<TaskVo> taskVos = this.taskList(taskCondition);
        if(CollectionUtil.isNotEmpty(taskVos)){
            return taskVos.get(0);
        } else{
            return null;
        }
    }
}
